// FacebookSession.cs
// Facebook/Framework/Service/Core
// Copyright (c) 2007, Nikhil Kothari. All Rights Reserved.
//

using System;
using System.Diagnostics;

namespace Facebook.Service.Core {

    /// <summary>
    /// A Facebook session represents a logical user login, and
    /// allows an application to access Facebook services in the context
    /// of the specific user.
    /// </summary>
    public abstract class FacebookSession {

        private string _appKey;
        private string _secret;

        private FacebookSessionType _sessionType;
        private string _sessionKey;
        private bool _sessionExpires;
        private string _userID;
        private string _pageUserID;
        private string[] _friendIDs;

        private FacebookResponse _lastResponse;

        /// <summary>
        /// Initializes an instance of a <see cref="FacebookSession" />.
        /// </summary>
        /// <param name="appKey">The application key representing the application.</param>
        /// <param name="secret">The application secret used to authenticate requests.</param>
        protected FacebookSession(string appKey, string secret) {
            Debug.Assert(String.IsNullOrEmpty(appKey) == false);
            Debug.Assert(String.IsNullOrEmpty(secret) == false);

            _appKey = appKey;
            _secret = secret;
        }

        /// <summary>
        /// The application key representing the application.
        /// </summary>
        public string ApplicationKey {
            get {
                return _appKey;
            }
        }

        internal string[] FriendIDs {
            get {
                return _friendIDs;
            }
        }

        /// <summary>
        /// The user ID of the user browsing the page.
        /// </summary>
        public string PageUserID {
            get {
                if (_sessionType != FacebookSessionType.PresencePage) {
                    return String.Empty;
                }
                return _pageUserID;
            }
        }

        /// <summary>
        /// The application secret used to authenticate requests.
        /// </summary>
        public string Secret {
            get {
                return _secret;
            }
        }

        /// <summary>
        /// Whether the session expires or is long-lived.
        /// </summary>
        public bool SessionExpires {
            get {
                return _sessionExpires;
            }
        }

        /// <summary>
        /// The unique identifier of the session.
        /// </summary>
        public string SessionKey {
            get {
                return _sessionKey;
            }
        }

        /// <summary>
        /// The type of the current session.
        /// </summary>
        public FacebookSessionType SessionType {
            get {
                return _sessionType;
            }
        }

        /// <summary>
        /// The ID of the user associated with the session.
        /// </summary>
        public string UserID {
            get {
                return _userID;
            }
        }

        /// <summary>
        /// The version of the Facebook API accessible with this session.
        /// </summary>
        public string Version {
            get {
                return "1.0";
            }
        }

        /// <summary>
        /// Gets the last response returned from the Facebook service for
        /// access to the raw response, and status code for diagnostics purposes.
        /// This may be null.
        /// </summary>
        /// <returns>The last response if available.</returns>
        public FacebookResponse GetLastResponse() {
            return _lastResponse;
        }

        /// <summary>
        /// Initializes the list of friend IDs associated with the user
        /// that is logged in under this session.
        /// </summary>
        /// <param name="friendIDs">The set of friend IDs.</param>
        protected void InitializeFriends(string[] friendIDs) {
            _friendIDs = friendIDs;
        }

        /// <summary>
        /// Initializes the session information once a session has been created.
        /// </summary>
        /// <param name="sessionKey">The unique identifier of the session.</param>
        /// <param name="sessionExpires">Whether the session expires or is long-lived.</param>
        /// <param name="sessionType">The type of the current session.</param>
        protected void InitializeSessionKey(string sessionKey, bool sessionExpires, FacebookSessionType sessionType) {
            if (String.IsNullOrEmpty(sessionKey)) {
                throw new ArgumentNullException("sessionKey");
            }
            if ((sessionType < FacebookSessionType.User) || (sessionType > FacebookSessionType.PresencePage)) {
                throw new ArgumentOutOfRangeException("sessionType");
            }
            if (_sessionKey != null) {
                throw new InvalidOperationException("SessionKey is already set.");
            }

            _sessionKey = sessionKey;
            _sessionExpires = sessionExpires;
            _sessionType = sessionType;
        }

        /// <summary>
        /// Initializes the user associated with this session.
        /// </summary>
        /// <param name="userID">The ID of the user associated with the session.</param>
        /// <param name="pageUserID">The ID of the user browsing the page if the session is associated with a presence page.</param>
        protected void InitializeUserID(string userID, string pageUserID) {
            if (String.IsNullOrEmpty(userID)) {
                throw new ArgumentNullException("userID");
            }
            if ((_sessionType == FacebookSessionType.PresencePage) &&
                String.IsNullOrEmpty(pageUserID)) {
                throw new ArgumentNullException("pageUserID");
            }
            if (_userID != null) {
                throw new InvalidOperationException("UserID is already set.");
            }

            _userID = userID;
            _pageUserID = pageUserID;
        }

        internal void LogResponse(FacebookResponse response) {
            _lastResponse = response;
        }

        /// <summary>
        /// Updates the secret to a new value that should be used for this session.
        /// This is used to accomplish the authentication mechanism provided by
        /// Facebook for desktop applications.
        /// </summary>
        /// <param name="secret">The updated secret key to use.</param>
        protected void UpdateSecret(string secret) {
            if (String.IsNullOrEmpty(secret)) {
                throw new ArgumentNullException("secret");
            }

            _secret = secret;
        }
    }
}
